package com.org.devg.dbcluster;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"com.org.devg.dbcluster"})
@EnableConfigurationProperties(DevgDbclusterConfig.class)
@ConditionalOnWebApplication
public class DevgDbclusterAutoConfiguration {

  private static Logger log = LoggerFactory.getLogger(DevgDbclusterAutoConfiguration.class);

  private static final Lock lock = new ReentrantLock();

  private static final AtomicInteger connectFailNumber = new AtomicInteger(0);

  private final DevgDbclusterConfig devgDbclusterConfig;

  public DevgDbclusterAutoConfiguration(DevgDbclusterConfig devgDbclusterConfig) {
    this.devgDbclusterConfig = devgDbclusterConfig;
  }

  @PostConstruct
  public void initDbclusterSchedule() {
    new Thread(new Runnable() {
      @Override
      public void run() {
        invokeDbclusterSchedule();
      }
    }).start();
  }

  private void invokeDbclusterSchedule() {
    while (true) {
      try {
        Integer checkIntervalSecond = 10;
        if (null != devgDbclusterConfig.getMasterConfig() && null != devgDbclusterConfig.getMasterConfig().getCheckIntervalSecond()) {
          checkIntervalSecond = devgDbclusterConfig.getMasterConfig().getCheckIntervalSecond();
        }
        Integer checkErrorCount = 3;
        if (null != devgDbclusterConfig.getMasterConfig() && null != devgDbclusterConfig.getMasterConfig().getCheckErrorCount()) {
          checkErrorCount = devgDbclusterConfig.getMasterConfig().getCheckErrorCount();
        }
        Integer timeout = 3;
        if (null != devgDbclusterConfig.getMasterConfig() && null != devgDbclusterConfig.getMasterConfig().getTimeOut()) {
          timeout = devgDbclusterConfig.getMasterConfig().getTimeOut();
        }
        devgDbclusterConfig.getMasterConfig().getTimeOut();
        lock.lock();
        try {
          String host = devgDbclusterConfig.getMasterConfig().getHost();
          Integer port = devgDbclusterConfig.getMasterConfig().getPort();

          Socket socket = new Socket();
          socket.connect(new InetSocketAddress(host, port), timeout * 1000);
          DevgMybatisConfiguration.dataSourceMap.put(DevgMybatisConfiguration.dataSourceType, "masterDataSource");
        } catch (Exception ex) {
          if (connectFailNumber.incrementAndGet() > checkErrorCount) {
            DevgMybatisConfiguration.dataSourceMap.put(DevgMybatisConfiguration.dataSourceType, "slaveDataSource");
          } else {
            log.error("init dbcluster Schedule error", ex);
          }
        } finally {
          lock.unlock();
        }
        Thread.sleep(checkIntervalSecond * 1000);
      } catch (Exception ex) {
        log.error("Exception when scan the timeout invocation of remoting.", ex);
      }
    }
  }
}
